home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / twnsck12.zip / SRC\WINSOCK.C < prev    next >
Text File  |  1994-12-03  |  49KB  |  2,047 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <winsock.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <dos.h>
  25. #include "twinsock.h"
  26. #include "tx.h"
  27.  
  28. #ifdef __MSDOS__
  29. #define    PORTSWAP(x)    ntohs(x)
  30. #else
  31. #define    PORTSWAP(x)    ntohl(x)
  32. #endif
  33.  
  34. static    int    iErrno = 0;
  35. static    short    idNext = 0;
  36.  
  37. static    struct    per_task    *pptList = 0;
  38. static    struct    per_socket    *ppsList = 0;
  39. static    struct    tx_queue    *ptxqList = 0;
  40.  
  41. HWND    hwndManager = 0;
  42. BOOL    bEstablished = 0;
  43.  
  44. static    void    FireAsyncRequest(struct tx_queue *ptxq);
  45.  
  46. void _export
  47. RegisterManager(HWND hwnd)
  48. {
  49.     hwndManager = hwnd;
  50. }
  51.  
  52. void _export
  53. SetInitialised(void)
  54. {
  55.     bEstablished = TRUE;
  56. }
  57.  
  58.  
  59. void
  60. CopyDataIn(    void        *pvSource,
  61.         enum arg_type    at,
  62.         void        *pvDest,
  63.         int        nLen)
  64. {
  65.     switch(at)
  66.     {
  67.     case AT_Int16:
  68.     case AT_Int16Ptr:
  69.         *(short *) pvDest = ntohs(*(short *) pvSource);
  70.         break;
  71.  
  72.     case AT_Int32:
  73.     case AT_Int32Ptr:
  74.         *(short *) pvDest = ntohl(*(short *) pvSource);
  75.         break;
  76.  
  77.     case AT_Char:
  78.         *(char *) pvDest = *(char *) pvSource;
  79.         break;
  80.  
  81.     case AT_GenPtr:
  82.     case AT_String:
  83.         memcpy(pvDest, pvSource, nLen);
  84.         break;
  85.     }
  86. }
  87.  
  88. void
  89. CopyDataOut(    void        *pvDest,
  90.         enum arg_type    at,
  91.         void        *pvSource,
  92.         int        nLen)
  93. {
  94.     switch(at)
  95.     {
  96.     case AT_Int16Ptr:
  97.     case AT_Int16:
  98.         *(short *) pvDest = htons(*(short *) pvSource);
  99.         break;
  100.  
  101.     case AT_Int32:
  102.     case AT_Int32Ptr:
  103.         *(short *) pvDest = htonl(*(short *) pvSource);
  104.         break;
  105.  
  106.     case AT_Char:
  107.         *(char *) pvDest = *(char *) pvSource;
  108.         break;
  109.  
  110.     case AT_GenPtr:
  111.     case AT_String:
  112.         memcpy(pvDest, pvSource, nLen);
  113.         break;
  114.     }
  115. }
  116.  
  117. static    struct    per_task *
  118. GetAnotherTaskInfo(HTASK htask)
  119. {
  120.     struct per_task *ppt;
  121.  
  122.     for (ppt = pptList; ppt; ppt = ppt->pptNext)
  123.     {
  124.         if (ppt->htask == htask)
  125.             return ppt;
  126.     }
  127.     iErrno = WSANOTINITIALISED;
  128.     return 0;
  129. }
  130.  
  131. static    struct    per_task *
  132. GetTaskInfo(void)
  133. {
  134.     return GetAnotherTaskInfo(GetCurrentTask());
  135. }
  136.  
  137.  
  138. static    struct    per_socket *
  139. GetSocketInfo(SOCKET s)
  140. {
  141.     struct per_socket *pps;
  142.  
  143.  
  144.     for (pps = ppsList; pps; pps = pps->ppsNext)
  145.     {
  146.         if (pps->s == s)
  147.             return pps;
  148.     }
  149.     iErrno = WSAENOTSOCK;
  150.     return 0;
  151. }
  152.  
  153. static    void
  154. Notify(struct per_socket *pps,
  155.     int iCode)
  156. {
  157.     if (pps->iEvents & iCode)
  158.         PostMessage(pps->hWnd, pps->wMsg, pps->s, WSAMAKESELECTREPLY(iCode, 0));
  159. }
  160.  
  161. static    struct    per_socket *
  162. NewSocket(struct per_task *ppt, SOCKET s)
  163. {
  164.     struct per_socket *ppsNew;
  165.  
  166.     ppsNew = (struct per_socket *) malloc(sizeof(struct per_socket));
  167.     ppsNew->s = s;
  168.     ppsNew->iFlags = 0;
  169.     ppsNew->pdIn = 0;
  170.     ppsNew->pdOut = 0;
  171.     ppsNew->htaskOwner = ppt->htask;
  172.     ppsNew->ppsNext = ppsList;
  173.     ppsNew->iEvents = 0;
  174.     ppsList = ppsNew;
  175.     return ppsNew;
  176.     
  177. }
  178.  
  179. static void SendEarlyClose(SOCKET s);
  180.  
  181. static    void
  182. RemoveSocket(struct per_socket *pps)
  183. {
  184.     struct    per_socket **ppps, *ppsParent;
  185.     struct    data    **ppd, *pd;
  186.  
  187.     /* If our parent has noticed we're here, we need to remove ourselves
  188.      * from the list of sockets awaiting acception.
  189.      */
  190.     for (ppsParent = ppsList; ppsParent; ppsParent = ppsParent->ppsNext)
  191.     {
  192.         if (!(ppsParent->iFlags & PSF_ACCEPT))
  193.             continue;
  194.         for (ppd = &ppsParent->pdIn; *ppd; ppd = &(*ppd)->pdNext)
  195.         {
  196.             if ((*ppd)->pchData == (char *) pps)
  197.             {
  198.                 pd = *ppd;
  199.                 *ppd = pd->pdNext;
  200.                 free(pd);
  201.             }
  202.         }
  203.     }
  204.  
  205.     /* Find our own position in the list */
  206.     for (ppps = &ppsList; *ppps; ppps = &(*ppps)->ppsNext)
  207.     {
  208.         if (*ppps == pps)
  209.         {
  210.             *ppps = pps->ppsNext;
  211.  
  212.             /* If we have unacknowledged children, kill them */
  213.             while (pps->pdIn)
  214.             {
  215.                 pd = pps->pdIn;
  216.                 pps->pdIn = pd->pdNext;
  217.                 if (pps->iFlags & PSF_ACCEPT)
  218.                 {
  219.                     SendEarlyClose(((struct per_socket *) pd->pchData)->s);
  220.                     RemoveSocket((struct per_socket *) pd->pchData);
  221.                 }
  222.                 else
  223.                 {
  224.                     free(pd->pchData);
  225.                 }
  226.                 free(pd);
  227.             }
  228.             free(pps);
  229.             return;
  230.         }
  231.     }
  232. }
  233.  
  234. static    void
  235. DataReceived(SOCKET s, void *pvData, int nLen, enum Functions ft)
  236. {
  237.     struct    data    *pdNew, **ppdList;
  238.     struct    per_socket *pps, *ppsNew;
  239.     struct    per_task *ppt;
  240.     int        ns;
  241.  
  242.     pps = GetSocketInfo(s);
  243.     if (!pps)
  244.     {
  245.         if (ft == FN_Accept)
  246.         {
  247.             nLen -= sizeof(struct sockaddr_in);
  248.             pvData = (char *) pvData + sizeof(struct sockaddr_in);
  249.             if (nLen == sizeof(long))
  250.                 ns = ntohl(*(long *) pvData);
  251.             else
  252.                 ns = ntohs(*(short*) pvData);
  253.             SendEarlyClose(ns);
  254.         }
  255.         return;
  256.     }
  257.     for (ppdList = &pps->pdIn; *ppdList; ppdList = &(*ppdList)->pdNext);
  258.  
  259.     pdNew = (struct data *) malloc(sizeof(struct data));
  260.     pdNew->sin = *(struct sockaddr_in *) pvData;
  261.     pdNew->sin.sin_family = ntohs(pdNew->sin.sin_family);
  262.  
  263.     nLen -= sizeof(struct sockaddr_in);
  264.     pvData = (char *) pvData + sizeof(struct sockaddr_in);
  265.  
  266.     pdNew->pdNext = 0;
  267.     pdNew->nUsed = 0;
  268.     *ppdList = pdNew;
  269.  
  270.     /* Note that the calls to Notify below should *really*
  271.      * only be made if the data gets put at the head of the
  272.      * queue, but some telnet implementations miss notifications
  273.      * and this screws us right up. By putting in additional
  274.      * notifications we at least have a chance of recovery.
  275.      */
  276.     if (pps->iFlags & PSF_ACCEPT)
  277.     {
  278.         pdNew->iLen = 0;
  279.         if (nLen == sizeof(long))
  280.             ns = ntohl(*(long *) pvData);
  281.         else
  282.             ns = ntohs(*(short*) pvData);
  283.         ppt = GetAnotherTaskInfo(pps->htaskOwner);
  284.         ppsNew = NewSocket(ppt, ns);
  285.         pdNew->pchData = (char *) ppsNew;
  286.         ppsNew->iFlags |= PSF_CONNECT;
  287.         Notify(pps, FD_ACCEPT);
  288.     }
  289.     else
  290.     {
  291.         pdNew->iLen = nLen;
  292.         pdNew->pchData = (char *) malloc(nLen);
  293.         memcpy(pdNew->pchData, pvData, nLen);
  294.         Notify(pps, nLen ? FD_READ : FD_CLOSE);
  295.     }
  296. }
  297.  
  298. static    BOOL
  299. StartBlocking(struct per_task *ppt)
  300. {
  301.     if (ppt->bBlocking)
  302.     {
  303.         iErrno = WSAEINPROGRESS;
  304.         return FALSE;
  305.     }
  306.     else
  307.     {
  308.         ppt->bBlocking = TRUE;
  309.         ppt->bCancel = FALSE;
  310.         return TRUE;
  311.     }
  312. }
  313.  
  314. static    void
  315. EndBlocking(struct per_task *ppt)
  316. {
  317.     ppt->bBlocking = FALSE;
  318. }
  319.  
  320. static    BOOL
  321. FlushMessages(struct per_task *ppt)
  322. {
  323.     MSG msg;
  324.     BOOL ret;
  325.  
  326.     if (ppt->lpBlockFunc)
  327.         return ((BOOL far pascal (*)()) ppt->lpBlockFunc)();
  328.  
  329.      ret = (BOOL) PeekMessage(&msg,0,0,0,PM_REMOVE);
  330.     if (ret)
  331.     {
  332.         TranslateMessage(&msg);
  333.         DispatchMessage(&msg);
  334.         /* Some poorly behaved applications quit without
  335.          * checking the return value of WSACancel. It
  336.          * *can* fail.
  337.          */
  338.         if (msg.message == WM_QUIT)
  339.             ppt->bCancel = TRUE;
  340.     }
  341.     return ret;
  342. }
  343.  
  344. static    void
  345. RemoveTXQ(struct tx_queue *ptxq)
  346. {
  347.     struct    tx_queue **pptxq;
  348.  
  349.     for (pptxq = &ptxqList; *pptxq; pptxq = &((*pptxq)->ptxqNext))
  350.     {
  351.         if (*pptxq == ptxq)
  352.         {
  353.             *pptxq = ptxq->ptxqNext;
  354.             free(ptxq->ptxr);
  355.             free(ptxq);
  356.             return;
  357.         }
  358.     }
  359. }
  360.  
  361. static    void
  362. RemoveTask(struct per_task *ppt)
  363. {
  364.     struct per_task **pppt;
  365.  
  366.     for (pppt = &pptList; *pppt; pppt = &((*pppt)->pptNext))
  367.     {
  368.         if (*pppt == ppt)
  369.         {
  370.             *pppt = ppt->pptNext;
  371.             free(ppt);
  372.         }
  373.     }
  374. };
  375.  
  376. void far _export
  377. ResponseReceived(struct tx_request *ptxr)
  378. {
  379.     int        nLen;
  380.     int        id;
  381.     struct    tx_queue *ptxq;
  382.     enum Functions    ft;
  383.  
  384.     ft = (enum Functions) ntohs(ptxr->iType);
  385.     id = ntohs(ptxr->id);
  386.     nLen = ntohs(ptxr->nLen);
  387.     if (ft == FN_Data || ft == FN_Accept)
  388.     {
  389.         DataReceived(id, ptxr->pchData, nLen - sizeof(short) * 5, ft);
  390.         return;
  391.     }
  392.     for (ptxq = ptxqList; ptxq; ptxq = ptxq->ptxqNext)
  393.     {
  394.         if (ptxq->id == id)
  395.         {
  396.             memcpy(ptxq->ptxr, ptxr, nLen);
  397.             ptxq->bDone = TRUE;
  398.             if (ptxq->pchLocation)
  399.                 FireAsyncRequest(ptxq);
  400.             return;
  401.         }
  402.     }
  403. }
  404.  
  405. static    struct tx_queue *
  406. TransmitFunction(struct transmit_function *ptf)
  407. {
  408.     int    i;
  409.     int    nSize = sizeof(short) * 5;
  410.     struct    tx_request *ptxr;
  411.     struct    tx_queue *ptxq, **pptxq;
  412.     int    iOffset;
  413.  
  414.     for (i = 0; i < ptf->nArgs; i++)
  415.         nSize += ptf->pfaList[i].iLen + sizeof(short) * 2;
  416.     nSize += ptf->pfaResult->iLen + sizeof(short) * 2;
  417.     ptxr = (struct tx_request *) malloc(nSize);
  418.     ptxr->iType = htons((short) ptf->fn);
  419.     ptxr->nArgs = htons((short) ptf->nArgs);
  420.     ptxr->nError = 0;
  421.     ptxr->nLen = htons((short) nSize);
  422.     ptxr->id = htons(idNext);
  423.     for (iOffset = i = 0; i < ptf->nArgs; i++)
  424.     {
  425.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].at);
  426.         iOffset += 2;
  427.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].iLen);
  428.         iOffset += 2;
  429.         CopyDataOut(    ptxr->pchData + iOffset,
  430.                 ptf->pfaList[i].at,
  431.                 ptf->pfaList[i].pvData,
  432.                 ptf->pfaList[i].iLen);
  433.         iOffset += ptf->pfaList[i].iLen;
  434.     }
  435.     *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->at);
  436.     iOffset += 2;
  437.     *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->iLen);
  438.     iOffset += 2;
  439.     CopyDataOut(    ptxr->pchData + iOffset,
  440.             ptf->pfaResult->at,
  441.             ptf->pfaResult->pvData,
  442.             ptf->pfaResult->iLen);
  443.  
  444.     iOffset += ptf->pfaResult->iLen;
  445.  
  446.     ptxq = (struct tx_queue *) malloc(sizeof(struct tx_queue));
  447.     ptxq->ptxqNext = 0;
  448.     ptxq->id = idNext;
  449.     ptxq->ptxr = ptxr;
  450.     ptxq->bDone = 0;
  451.     ptxq->hwnd = 0;
  452.     ptxq->pchLocation = 0;
  453.     ptxq->wMsg = 0;
  454.     idNext++;
  455.     for (pptxq = &ptxqList; *pptxq; pptxq = &((*pptxq)->ptxqNext));
  456.     *pptxq = ptxq;
  457.     SendMessage(hwndManager, WM_USER, nSize, (LPARAM) ptxr);
  458.     return ptxq;
  459. };
  460.  
  461. static void
  462. SendEarlyClose(SOCKET s)
  463. {
  464.     struct    func_arg pfaArgs[1];
  465.     struct    func_arg pfaReturn;
  466.     struct    transmit_function tf;
  467.     int    nReturn;
  468.  
  469.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  470.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  471.     INIT_TF(tf, FN_Close, 1, pfaArgs, pfaReturn);
  472.     RemoveTXQ(TransmitFunction(&tf));
  473. }
  474.  
  475. static void
  476. SetErrorResult(struct func_arg *pfaResult)
  477. {
  478.     switch (pfaResult->at)
  479.     {
  480.     case AT_Int16:
  481.         *(short *) pfaResult->pvData = -1;
  482.         break;
  483.  
  484.     case AT_Int32:
  485.         *(long *) pfaResult->pvData = -1;
  486.         break;
  487.  
  488.     case AT_Char:
  489.         *(char *) pfaResult->pvData = -1;
  490.         break;
  491.  
  492.     case AT_Int16Ptr:
  493.     case AT_Int32Ptr:
  494.     case AT_String:
  495.     case AT_GenPtr:
  496.         *(void **) pfaResult->pvData = 0;
  497.         break;
  498.     }
  499. }
  500.  
  501. static    int    TransmitFunctionAndBlock(
  502.             struct per_task *ppt,
  503.             struct transmit_function *ptf)
  504. {
  505.     struct tx_queue *ptxq;
  506.     struct tx_request *ptxr;
  507.     int    i, iOffset;
  508.     BOOL    bError = FALSE;
  509.  
  510.     if (!StartBlocking(ppt))
  511.     {
  512.         iErrno = WSAEINPROGRESS;
  513.         SetErrorResult(ptf->pfaResult);
  514.         return 0;
  515.     }
  516.     ptxq = TransmitFunction(ptf);
  517.     ptxr = ptxq->ptxr;
  518.     while (!ptxq->bDone)
  519.     {
  520.         FlushMessages(ppt);
  521.         if (ppt->bCancel)
  522.         {
  523.             iErrno = WSAEINTR;
  524.             RemoveTXQ(ptxq);
  525.             SetErrorResult(ptf->pfaResult);
  526.             EndBlocking(ppt);
  527.             return 0;
  528.         }
  529.     }
  530.     if (ptxq->ptxr->nError)
  531.     {
  532.         iErrno = ntohs(ptxq->ptxr->nError);
  533.         SetErrorResult(ptf->pfaResult);
  534.         bError = TRUE;
  535.     }
  536.     else
  537.     {
  538.         for (iOffset = i = 0; i < ptf->nArgs; i++)
  539.         {
  540.             *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].at);
  541.             iOffset += 2;
  542.             *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaList[i].iLen);
  543.             iOffset += 2;
  544.             if (!ptf->pfaList[i].bConstant)
  545.                 CopyDataIn(    ptxr->pchData + iOffset,
  546.                         ptf->pfaList[i].at,
  547.                         ptf->pfaList[i].pvData,
  548.                         ptf->pfaList[i].iLen);
  549.             iOffset += ptf->pfaList[i].iLen;
  550.         }
  551.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->at);
  552.         iOffset += 2;
  553.         *(short *) (ptxr->pchData + iOffset) = htons((short) ptf->pfaResult->iLen);
  554.         iOffset += 2;
  555.         CopyDataIn(    ptxr->pchData + iOffset,
  556.                 ptf->pfaResult->at,
  557.                 ptf->pfaResult->pvData,
  558.                 ptf->pfaResult->iLen);
  559.  
  560.     }
  561.     RemoveTXQ(ptxq);
  562.     EndBlocking(ppt);
  563.     return bError ? 0 : 1;
  564. }
  565.  
  566. static void
  567. CopyHostEnt(struct per_task *ppt)
  568. {
  569.     int    iLocation;
  570.     int    i;
  571.     int    nAddrs;
  572.  
  573.     ppt->he.h_addrtype = ntohs(*(short *) ppt->achHostEnt);
  574.     ppt->he.h_length = ntohs(*(short *) (ppt->achHostEnt + sizeof(short)));
  575.     nAddrs = ntohs(*(short *) (ppt->achHostEnt + sizeof(short) * 2));
  576.     iLocation = sizeof(short) * 3;
  577.     for (i = 0; i < nAddrs; i++)
  578.     {
  579.         if (i < MAX_ALTERNATES - 1)
  580.             ppt->apchHostAddresses[i] = ppt->achHostEnt + iLocation;
  581.         iLocation += 4;
  582.     }
  583.     if (nAddrs < MAX_ALTERNATES - 1)
  584.         ppt->apchHostAddresses[nAddrs] = 0;
  585.     else
  586.         ppt->apchHostAddresses[MAX_ALTERNATES - 1] = 0;
  587.     ppt->he.h_addr_list = ppt->apchHostAddresses;
  588.     ppt->he.h_name = ppt->achHostEnt + iLocation;
  589.     iLocation += strlen(ppt->achHostEnt + iLocation)+ 1;
  590.     for (i = 0; ppt->achHostEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  591.     {
  592.         ppt->apchHostAlii[i] = ppt->achHostEnt + iLocation;
  593.         iLocation += strlen(ppt->achHostEnt + iLocation)+ 1;
  594.     }
  595.     ppt->apchHostAlii[i] = 0;
  596.     ppt->he.h_aliases = ppt->apchHostAlii;
  597.     ppt->he.h_addr_list = ppt->apchHostAddresses;
  598. }
  599.  
  600. static int
  601. CopyHostEntTo(struct per_task *ppt, char *pchData)
  602. {
  603.     int    i;
  604.     int    nAddrs;
  605.     struct hostent *phe;
  606.     char    *pchOld;
  607.     int    nAlii;
  608.  
  609.     CopyHostEnt(ppt);
  610.  
  611.     phe = (struct hostent *) pchData;
  612.     memcpy(phe, &ppt->he, sizeof(ppt->he));
  613.  
  614.     pchData += sizeof(*phe);
  615.  
  616.     for (nAddrs = 0; phe->h_addr_list[nAddrs]; nAddrs++);
  617.     for (nAlii = 0; phe->h_aliases[nAlii]; nAlii++);
  618.  
  619.     memcpy(pchData, phe->h_addr_list, sizeof(char *) * (nAddrs + 1));
  620.     phe->h_addr_list = (char **) pchData;
  621.     pchData += sizeof(char *) * (nAddrs + 1);
  622.  
  623.     memcpy(pchData, phe->h_aliases, sizeof(char *) * (nAddrs + 1));
  624.     phe->h_aliases = (char **) pchData;
  625.     pchData += sizeof(char *) * (nAddrs + 1);
  626.  
  627.     pchOld = phe->h_addr_list[0];
  628.     memcpy(pchData, pchOld, 4 * nAddrs);
  629.     for (i = 0; i < nAddrs; i++)
  630.         phe->h_addr_list[i] = phe->h_addr_list[i] - pchOld + pchData;
  631.     pchData += 4 * nAddrs;
  632.  
  633.     strcpy(pchData, phe->h_name);
  634.     phe->h_name = pchData;
  635.     pchData += strlen(pchData) + 1;
  636.  
  637.     for (i = 0; i < nAlii; i++)
  638.     {
  639.         strcpy(pchData, phe->h_aliases[i]);
  640.         phe->h_aliases[i] = pchData;
  641.         pchData += strlen(pchData) + 1;
  642.     }
  643.     return (pchData - (char *) phe);
  644. }
  645.  
  646. static void
  647. CopyServEnt(struct per_task *ppt)
  648. {
  649.     int    iLocation;
  650.     int    i;
  651.  
  652.     /* Note that s_port is needed in network byte order */
  653.         ppt->se.s_port = *(short *) ppt->achServEnt;
  654.     iLocation = sizeof(short);
  655.     ppt->se.s_proto = ppt->achServEnt + iLocation;
  656.     iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  657.     ppt->se.s_name = ppt->achServEnt + iLocation;
  658.     iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  659.     for (i = 0; ppt->achServEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  660.     {
  661.         ppt->apchServAlii[i] = ppt->achServEnt + iLocation;
  662.         iLocation += strlen(ppt->achServEnt + iLocation) + 1;
  663.     }
  664.     ppt->apchServAlii[i] = 0;
  665.     ppt->se.s_aliases = ppt->apchServAlii;
  666. }
  667.  
  668. static int
  669. CopyServEntTo(struct per_task *ppt, char *pchData)
  670. {
  671.     int    i;
  672.     int    nAlii;
  673.     struct    servent *pse;
  674.  
  675.     CopyServEnt(ppt);
  676.  
  677.     pse = (struct servent *) pchData;
  678.     memcpy(pse, &ppt->se, sizeof(ppt->se));
  679.     pchData += sizeof(*pse);
  680.  
  681.     for (nAlii = 0; pse->s_aliases[nAlii]; nAlii++);
  682.     memcpy(pchData, pse->s_aliases, sizeof(char *) * (nAlii + 1));
  683.     pse->s_aliases = (char **) pchData;
  684.     pchData += sizeof(char *) * (nAlii + 1);
  685.  
  686.     strcpy(pchData, ppt->se.s_name);
  687.     ppt->se.s_name = pchData;
  688.     pchData += strlen(pchData) + 1;
  689.  
  690.     strcpy(pchData, ppt->se.s_proto);
  691.     ppt->se.s_proto = pchData;
  692.     pchData += strlen(pchData) + 1;
  693.  
  694.     for (i = 0; i < nAlii; i++)
  695.     {
  696.         strcpy(pchData, pse->s_aliases[i]);
  697.         pse->s_aliases[i] = pchData;
  698.         pchData += strlen(pchData) + 1;
  699.     }
  700.     return (pchData - (char *) pse);
  701. }
  702.  
  703. static void
  704. CopyProtoEnt(struct per_task *ppt)
  705. {
  706.     int    iLocation;
  707.     int    i;
  708.     int    nAddrs;
  709.  
  710.     ppt->pe.p_proto = ntohs(*(short *) ppt->achProtoEnt);
  711.     iLocation = sizeof(short);
  712.     ppt->pe.p_name = ppt->achProtoEnt + iLocation;
  713.     iLocation += strlen(ppt->achProtoEnt + iLocation) + 1;
  714.     for (i = 0; ppt->achProtoEnt[iLocation] && i < MAX_ALTERNATES - 1; i++)
  715.     {
  716.         ppt->apchProtoAlii[i] = ppt->achProtoEnt + iLocation;
  717.         iLocation += strlen(ppt->achProtoEnt + iLocation) + 1;
  718.     }
  719.     ppt->apchProtoAlii[i] = 0;
  720.     ppt->pe.p_aliases = ppt->apchProtoAlii;
  721. }
  722.  
  723. static int
  724. CopyProtoEntTo(struct per_task *ppt, char *pchData)
  725. {
  726.     int    iLocation;
  727.     int    i;
  728.     int    nAlii;
  729.     struct    protoent *ppe;
  730.  
  731.     CopyProtoEnt(ppt);
  732.  
  733.     ppe = (struct protoent *) pchData;
  734.     memcpy(ppe, &ppt->pe, sizeof(ppt->pe));
  735.     pchData += sizeof(*ppe);
  736.  
  737.     for (nAlii = 0; ppe->p_aliases[nAlii]; nAlii++);
  738.     memcpy(pchData, ppe->p_aliases, sizeof(char *) * (nAlii + 1));
  739.     ppe->p_aliases = (char **) pchData;
  740.     pchData += sizeof(char *) * (nAlii + 1);
  741.  
  742.     strcpy(pchData, ppe->p_name);
  743.     ppe->p_name = pchData;
  744.     pchData += strlen(pchData) + 1;
  745.  
  746.     for (i = 0; i < nAlii; i++)
  747.     {
  748.         strcpy(pchData, ppe->p_aliases[i]);
  749.         ppe->p_aliases[i] = pchData;
  750.         pchData += strlen(pchData) + 1;
  751.     }
  752.     return (pchData - (char *) ppe);
  753. }
  754.  
  755. SOCKET pascal far _export
  756. accept(SOCKET s, struct sockaddr FAR *addr,
  757.                           int FAR *addrlen)
  758. {
  759.     struct per_task *ppt;
  760.     struct per_socket *pps, *ppsNew;
  761.     struct data *pd;
  762.  
  763.     if ((ppt = GetTaskInfo()) == 0)
  764.         return -1;
  765.     if ((pps = GetSocketInfo(s)) == 0)
  766.         return -1;
  767.     if (!(pps->iFlags & PSF_ACCEPT))
  768.     {
  769.         iErrno = WSAEINVAL;
  770.         return -1;
  771.     }
  772.     if (!pps->pdIn && (pps->iFlags & PSF_NONBLOCK))
  773.     {
  774.         iErrno = WSAEWOULDBLOCK;
  775.         return -1;
  776.     }
  777.     if (!StartBlocking(ppt))
  778.         return -1;
  779.     while (!pps->pdIn)
  780.     {
  781.         FlushMessages(ppt);
  782.         if (ppt->bCancel)
  783.         {
  784.             iErrno = WSAEINTR;
  785.             EndBlocking(ppt);
  786.             return -1;
  787.         }
  788.     }
  789.  
  790.     pd = pps->pdIn;
  791.     if (addr && addrlen)
  792.     {
  793.         memcpy(addr, &pd->sin, sizeof(pd->sin));
  794.         *addrlen = sizeof(pd->sin);
  795.     }
  796.     ppsNew = (struct per_socket *) pd->pchData;
  797.  
  798.     pps->pdIn = pd->pdNext;
  799.     free(pd);
  800.     if (pps->pdIn)
  801.         Notify(pps, FD_ACCEPT);
  802.  
  803.     EndBlocking(ppt);
  804.     return ppsNew->s;
  805. }
  806.  
  807. int pascal far _export
  808. bind(SOCKET s, const struct sockaddr FAR *addr, int namelen)
  809. {
  810.     struct per_task *ppt;
  811.     struct per_socket *pps;
  812.     int    nReturn;
  813.     struct    func_arg pfaArgs[3];
  814.     struct    func_arg pfaReturn;
  815.     struct    transmit_function tf;
  816.     struct    sockaddr    *psa;
  817.  
  818.     if ((ppt = GetTaskInfo()) == 0)
  819.         return -1;
  820.     if (!GetSocketInfo(s))
  821.         return -1;
  822.     psa = (struct sockaddr *) malloc(namelen);
  823.     memcpy(psa, addr, namelen);
  824.     psa->sa_family = htons(psa->sa_family);
  825.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  826.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    psa,        namelen            );
  827.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &namelen,    sizeof(namelen)        );
  828.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  829.     INIT_TF(tf, FN_Bind, 3, pfaArgs, pfaReturn);
  830.     TransmitFunctionAndBlock(ppt, &tf);
  831.     free(psa);
  832.     return nReturn;
  833. }
  834.  
  835. int pascal far _export
  836. closesocket(SOCKET s)
  837. {
  838.     struct per_task *ppt;
  839.     struct per_socket *pps;
  840.     int    nReturn;
  841.     struct    func_arg pfaArgs[1];
  842.     struct    func_arg pfaReturn;
  843.     struct    transmit_function tf;
  844.  
  845.     if ((ppt = GetTaskInfo()) == 0)
  846.         return -1;
  847.     if ((pps = GetSocketInfo(s)) == 0)
  848.         return -1;
  849.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  850.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  851.     INIT_TF(tf, FN_Close, 1, pfaArgs, pfaReturn);
  852.     TransmitFunctionAndBlock(ppt, &tf);
  853.     RemoveSocket(pps); /* Assume success. Is this valid? */
  854.     return nReturn;
  855. }
  856.  
  857. int pascal far _export
  858. connect(SOCKET s, const struct sockaddr FAR *name, int namelen)
  859. {
  860.     struct per_task *ppt;
  861.     struct per_socket *pps;
  862.     int    nReturn;
  863.     struct    func_arg pfaArgs[3];
  864.     struct    func_arg pfaReturn;
  865.     struct    transmit_function tf;
  866.     struct    sockaddr    *psa;
  867.  
  868.     if ((ppt = GetTaskInfo()) == 0)
  869.         return -1;
  870.     if ((pps = GetSocketInfo(s)) == 0)
  871.         return -1;
  872.     psa = (struct sockaddr *) malloc(namelen);
  873.     memcpy(psa, name, namelen);
  874.     psa->sa_family = htons(psa->sa_family);
  875.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  876.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    psa,        namelen            );
  877.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &namelen,    sizeof(namelen)        );
  878.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  879.     INIT_TF(tf, FN_Connect, 3, pfaArgs, pfaReturn);
  880.     TransmitFunctionAndBlock(ppt, &tf);
  881.     free(psa);
  882.     if (nReturn != -1)
  883.         pps->iFlags |= PSF_CONNECT;
  884.     return nReturn;
  885. }
  886.  
  887. int pascal far _export
  888. ioctlsocket(SOCKET s, long cmd, u_long far * arg)
  889. {
  890.     struct per_task *ppt;
  891.     struct per_socket *pps;
  892.     int    nReturn;
  893.     struct    func_arg pfaArgs[3];
  894.     struct    func_arg pfaReturn;
  895.     struct    transmit_function tf;
  896.  
  897.     if ((ppt = GetTaskInfo()) == 0)
  898.         return -1;
  899.     if ((pps = GetSocketInfo(s)) == 0)
  900.         return -1;
  901.     switch(cmd)
  902.     {
  903.     case FIONBIO:
  904.         if (*arg)
  905.             pps->iFlags |= PSF_NONBLOCK;
  906.         else
  907.             pps->iFlags &= ~PSF_NONBLOCK;
  908.         break;
  909.  
  910.     case FIONREAD:
  911.         if (pps->pdIn)
  912.             *arg = pps->pdIn->iLen - pps->pdIn->nUsed;
  913.         else
  914.             *arg = 0;
  915.         break;
  916.  
  917.     case SIOCATMARK:
  918.         *(BOOL *) arg = 0;
  919.         break;
  920.     }
  921.     return 0;
  922. }
  923.  
  924. int pascal far _export getpeername (SOCKET s, struct sockaddr FAR *name,
  925.                             int FAR * namelen)
  926. {
  927.     struct per_task *ppt;
  928.     struct per_socket *pps;
  929.     int    nReturn;
  930.     struct    func_arg pfaArgs[3];
  931.     struct    func_arg pfaReturn;
  932.     struct    transmit_function tf;
  933.  
  934.     if ((ppt = GetTaskInfo()) == 0)
  935.         return -1;
  936.     if (!GetSocketInfo(s))
  937.         return -1;
  938.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  939.     INIT_ARGS(pfaArgs[1],    AT_GenPtr,    name,        *namelen        );
  940.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    namelen,    sizeof(*namelen)    );
  941.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  942.     INIT_TF(tf, FN_GetPeerName, 3, pfaArgs, pfaReturn);
  943.     TransmitFunctionAndBlock(ppt, &tf);
  944.     if (nReturn != -1)
  945.         name->sa_family = ntohs(name->sa_family);
  946.     return nReturn;
  947. }
  948.  
  949. int pascal far _export getsockname (SOCKET s, struct sockaddr FAR *name,
  950.                             int FAR * namelen)
  951. {
  952.     struct per_task *ppt;
  953.     struct per_socket *pps;
  954.     int    nReturn;
  955.     struct    func_arg pfaArgs[3];
  956.     struct    func_arg pfaReturn;
  957.     struct    transmit_function tf;
  958.  
  959.     if ((ppt = GetTaskInfo()) == 0)
  960.         return -1;
  961.     if (!GetSocketInfo(s))
  962.         return -1;
  963.     *namelen = sizeof(struct sockaddr_in); /* Just in case */
  964.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  965.     INIT_ARGS(pfaArgs[1],    AT_GenPtr,    name,        *namelen        );
  966.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    namelen,    sizeof(*namelen)    );
  967.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  968.     INIT_TF(tf, FN_GetSockName, 3, pfaArgs, pfaReturn);
  969.     TransmitFunctionAndBlock(ppt, &tf);
  970.     if (nReturn != -1)
  971.         name->sa_family = ntohs(name->sa_family);
  972.     return nReturn;
  973. }
  974.  
  975. int pascal far _export getsockopt (SOCKET s, int level, int optname,
  976.                            char FAR * optval, int FAR *optlen)
  977. {
  978.     struct per_task *ppt;
  979.     struct per_socket *pps;
  980.     int    nReturn;
  981.     struct    func_arg pfaArgs[5];
  982.     struct    func_arg pfaReturn;
  983.     struct    transmit_function tf;
  984.     long    iOptVal;
  985.     short    iOptLen;
  986.  
  987.     iOptLen = sizeof(long);
  988.  
  989.     if ((ppt = GetTaskInfo()) == 0)
  990.         return -1;
  991.     if (!GetSocketInfo(s))
  992.         return -1;
  993.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  994.     INIT_ARGS(pfaArgs[1],    AT_Int,        &level,        sizeof(level)        );
  995.     INIT_ARGS(pfaArgs[2],    AT_Int,        &optname,    sizeof(optname)        );
  996.     if (optname == SO_LINGER)
  997.         INIT_ARGS(pfaArgs[3],    AT_GenPtr,    optval,        iOptLen        );
  998.     else
  999.         INIT_ARGS(pfaArgs[3],    AT_Int32Ptr,    &iOptVal,    iOptLen        );
  1000.     INIT_ARGS(pfaArgs[4],    AT_IntPtr,    &iOptLen,    sizeof(iOptLen)        );
  1001.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1002.     INIT_TF(tf, FN_GetSockOpt, 5, pfaArgs, pfaReturn);
  1003.     if (TransmitFunctionAndBlock(ppt, &tf))
  1004.     {
  1005.         if (optname == SO_LINGER)
  1006.         {
  1007.             *optlen = sizeof(struct linger);
  1008.         }
  1009.         else
  1010.         {
  1011.             *optlen = sizeof(int);
  1012.             *optval = iOptVal;
  1013.         }
  1014.     }
  1015.     return nReturn;
  1016. }
  1017.  
  1018. u_long pascal far _export htonl (u_long hostlong)
  1019. {
  1020.     char    *pchValue = (char *) &hostlong;
  1021.     char    c;
  1022.  
  1023.     c = pchValue[0];
  1024.     pchValue[0] = pchValue[3];
  1025.     pchValue[3] = c;
  1026.     c = pchValue[1];
  1027.     pchValue[1] = pchValue[2];
  1028.     pchValue[2] = c;
  1029.     return hostlong;
  1030. }
  1031.  
  1032. u_short pascal far _export htons (u_short hostshort)
  1033. {
  1034.     char    *pchValue = (char *) &hostshort;
  1035.     char    c;
  1036.  
  1037.     c = pchValue[0];
  1038.     pchValue[0] = pchValue[1];
  1039.     pchValue[1] = c;
  1040.     return hostshort;
  1041. }
  1042.  
  1043. unsigned long pascal far _export inet_addr (const char FAR * cp)
  1044. {
  1045.     unsigned long    iValue;
  1046.     char    *pchValue = (char *) &iValue;
  1047.  
  1048.     if (!GetTaskInfo())
  1049.         return -1;
  1050.     pchValue[0] = atoi(cp);
  1051.     cp = strchr(cp, '.');
  1052.     if (cp)
  1053.     {
  1054.         cp++;
  1055.         pchValue[1] = atoi(cp);
  1056.         cp = strchr(cp, '.');
  1057.         if (cp)
  1058.         {
  1059.             cp++;
  1060.             pchValue[2] = atoi(cp);
  1061.             cp = strchr(cp, '.');
  1062.             if (cp)
  1063.             {
  1064.                 cp++;
  1065.                 pchValue[3] = atoi(cp);
  1066.                 cp = strchr(cp, '.');
  1067.                 if (!cp)
  1068.                 {
  1069.                     return iValue;
  1070.                 }
  1071.             }
  1072.         }
  1073.     }
  1074.     return -1;
  1075. }
  1076.  
  1077. char FAR * pascal far _export inet_ntoa (struct in_addr in)
  1078. {
  1079.     struct per_task *ppt;
  1080.  
  1081.     if ((ppt = GetTaskInfo()) == 0)
  1082.         return -1;
  1083.  
  1084.     sprintf(ppt->achAddress, "%d.%d.%d.%d",
  1085.             (int) in.S_un.S_un_b.s_b1,
  1086.             (int) in.S_un.S_un_b.s_b2,
  1087.             (int) in.S_un.S_un_b.s_b3,
  1088.             (int) in.S_un.S_un_b.s_b4);
  1089.     return ppt->achAddress;
  1090. }
  1091.  
  1092. int pascal far _export listen (SOCKET s, int backlog)
  1093. {
  1094.     struct per_task *ppt;
  1095.     struct per_socket *pps;
  1096.     int    nReturn;
  1097.     struct    func_arg pfaArgs[2];
  1098.     struct    func_arg pfaReturn;
  1099.     struct    transmit_function tf;
  1100.  
  1101.     if ((ppt = GetTaskInfo()) == 0)
  1102.         return -1;
  1103.     if ((pps = GetSocketInfo(s)) == 0)
  1104.         return -1;
  1105.     if (pps->iFlags & PSF_CONNECT)
  1106.     {
  1107.         iErrno = WSAEISCONN;
  1108.         return -1;
  1109.     }
  1110.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1111.     INIT_ARGS(pfaArgs[1],    AT_Int,        &backlog,    sizeof(backlog)        );
  1112.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1113.     INIT_TF(tf, FN_Listen, 2, pfaArgs, pfaReturn);
  1114.     TransmitFunctionAndBlock(ppt, &tf);
  1115.     if (nReturn != -1)
  1116.         pps->iFlags |= PSF_ACCEPT;
  1117.     return nReturn;
  1118. }
  1119.  
  1120. u_long pascal far _export ntohl (u_long netlong)
  1121. {
  1122.     char    *pchValue = (char *) &netlong;
  1123.     char    c;
  1124.  
  1125.     c = pchValue[0];
  1126.     pchValue[0] = pchValue[3];
  1127.     pchValue[3] = c;
  1128.     c = pchValue[1];
  1129.     pchValue[1] = pchValue[2];
  1130.     pchValue[2] = c;
  1131.     return netlong;
  1132. }
  1133.  
  1134. u_short pascal far _export ntohs (u_short netshort)
  1135. {
  1136.     char    *pchValue = (char *) &netshort;
  1137.     char    c;
  1138.  
  1139.     c = pchValue[0];
  1140.     pchValue[0] = pchValue[1];
  1141.     pchValue[1] = c;
  1142.     return netshort;
  1143. }
  1144.  
  1145. int pascal far _export recv (SOCKET s, char FAR * buf, int len, int flags)
  1146. {
  1147.     return recvfrom(s, buf, len, flags, 0, 0);
  1148. }
  1149.  
  1150. int pascal far _export recvfrom (SOCKET s, char FAR * buf, int len, int flags,
  1151.                          struct sockaddr FAR *from, int FAR * fromlen)
  1152. {
  1153.     struct per_task *ppt;
  1154.     struct per_socket *pps;
  1155.     struct data *pd;
  1156.  
  1157.     if ((ppt = GetTaskInfo()) == 0)
  1158.         return -1;
  1159.     if ((pps = GetSocketInfo(s)) == 0)
  1160.         return -1;
  1161.     if (pps->iFlags & PSF_CLOSED)
  1162.     {
  1163.         /* Haven't you got the message yet? */
  1164.         iErrno = WSAENOTCONN;
  1165.         return -1;
  1166.     }
  1167.     if (pps->iFlags & PSF_ACCEPT)
  1168.     {
  1169.         iErrno = WSAENOTCONN;
  1170.         return -1;
  1171.     }
  1172.     if (pps->iFlags & PSF_SHUTDOWN)
  1173.     {
  1174.         iErrno = WSAESHUTDOWN;
  1175.         return -1;
  1176.     }
  1177.     if (!pps->pdIn && (pps->iFlags & PSF_NONBLOCK))
  1178.     {
  1179.         iErrno = WSAEWOULDBLOCK;
  1180.         return -1;
  1181.     }
  1182.     if (!StartBlocking(ppt))
  1183.         return -1;
  1184.     while (!pps->pdIn)
  1185.     {
  1186.         FlushMessages(ppt);
  1187.         if (ppt->bCancel)
  1188.         {
  1189.             iErrno = WSAEINTR;
  1190.             EndBlocking(ppt);
  1191.             return -1;
  1192.         }
  1193.     }
  1194.  
  1195.     pd = pps->pdIn;
  1196.     if (from && fromlen)
  1197.     {
  1198.         memcpy(from, &pd->sin, sizeof(pd->sin));
  1199.         *fromlen = sizeof(pd->sin);
  1200.     }
  1201.     if (len > pd->iLen - pd->nUsed)
  1202.         len = pd->iLen - pd->nUsed;
  1203.     memcpy(buf, pd->pchData + pd->nUsed, len);
  1204.     pd->nUsed += len;
  1205.     if (pd->nUsed == pd->iLen)
  1206.     {
  1207.         pps->pdIn = pd->pdNext;
  1208.         free(pd->pchData);
  1209.         free(pd);
  1210.         if (pps->pdIn)
  1211.             Notify(pps, pps->pdIn->iLen ? FD_READ : FD_CLOSE);
  1212.     }
  1213.     else
  1214.     {
  1215.         Notify(pps, FD_READ);
  1216.     }
  1217.  
  1218.     EndBlocking(ppt);
  1219.     return len;
  1220. }
  1221.  
  1222. #define    PPS_ERROR    ((struct per_socket *) -1)
  1223.  
  1224. static    struct    per_socket **
  1225. GetPPS(fd_set *fds)
  1226. {
  1227.     struct per_socket **pps;
  1228.     int    i;
  1229.  
  1230.     if (!fds || !fds->fd_count)
  1231.         return 0;
  1232.     pps = (struct per_socket *) malloc(sizeof(struct per_socket *) *
  1233.                     fds->fd_count);
  1234.     for (i = 0; i < fds->fd_count; i++)
  1235.     {
  1236.         pps[i] = GetSocketInfo(fds->fd_array[i]);
  1237.         if (!pps[i])
  1238.         {
  1239.             free(pps);
  1240.             return PPS_ERROR;
  1241.         }
  1242.     }
  1243.     return pps;
  1244. }
  1245.  
  1246.  
  1247. int pascal far _export select (int nfds, fd_set *readfds, fd_set far *writefds,
  1248.                 fd_set *exceptfds, const struct timeval far *timeout)
  1249. {
  1250.     struct per_task *ppt;
  1251.     struct per_socket **ppsRead, **ppsWrite, **ppsExcept;
  1252.     BOOL    bOneOK = FALSE;
  1253.     BOOL    bTimedOut = FALSE;
  1254.     int    iOld, iNew;
  1255.     unsigned    long    tExpire;
  1256.     int    i;
  1257.  
  1258.     if (timeout)
  1259.     {
  1260.         tExpire = GetTickCount();
  1261.         tExpire += timeout->tv_usec / 1000 + timeout->tv_sec * 1000;
  1262.     }
  1263.     if ((ppt = GetTaskInfo()) == 0)
  1264.         return -1;
  1265.     if (!StartBlocking(ppt))
  1266.         return -1;
  1267.  
  1268.     ppsRead = GetPPS(readfds);
  1269.     if (ppsRead == PPS_ERROR)
  1270.         return -1;
  1271.     ppsWrite = GetPPS(writefds);
  1272.     if (ppsWrite == PPS_ERROR)
  1273.     {
  1274.         free(ppsRead);
  1275.         return -1;
  1276.     }
  1277.     ppsExcept = GetPPS(exceptfds);
  1278.     if (ppsExcept == PPS_ERROR)
  1279.     {
  1280.         free(ppsRead);
  1281.         free(ppsWrite);
  1282.         return -1;
  1283.     }
  1284.         
  1285.     while (!bOneOK && !bTimedOut && !ppt->bCancel)
  1286.     {
  1287.         FlushMessages(ppt);
  1288.         if (ppsWrite)
  1289.             bOneOK = TRUE;
  1290.         if (ppsRead)
  1291.         {
  1292.             for (i = 0; i < readfds->fd_count; i++)
  1293.             {
  1294.                 if (ppsRead[i]->pdIn)
  1295.                     bOneOK = TRUE;
  1296.             }
  1297.         }
  1298.         if (timeout && GetTickCount() >= tExpire)
  1299.             bTimedOut = TRUE;
  1300.     }
  1301.  
  1302.     nfds = 0;
  1303.     if (readfds)
  1304.     {
  1305.         for (iOld = iNew = 0; iOld < readfds->fd_count; iOld++)
  1306.         {
  1307.             if (iOld != iNew)
  1308.                 readfds->fd_array[iNew] =
  1309.                         readfds->fd_array[iOld];
  1310.             if (ppsRead[iOld]->pdIn)
  1311.                 iNew++;
  1312.         }
  1313.         readfds->fd_count = iNew;
  1314.         nfds += iNew;
  1315.     }
  1316.     if (writefds)
  1317.         nfds += writefds->fd_count;
  1318.     if (exceptfds)
  1319.         exceptfds->fd_count = 0;
  1320.  
  1321.     EndBlocking(ppt);
  1322.     if (ppsRead)
  1323.         free(ppsRead);
  1324.     if (ppsWrite)
  1325.         free(ppsWrite);
  1326.     if (ppsExcept)
  1327.         free(ppsExcept);
  1328.     if (ppt->bCancel && !nfds)
  1329.     {
  1330.         iErrno = WSAEINTR;
  1331.         return -1;
  1332.     }
  1333.     else
  1334.     {
  1335.         return nfds;
  1336.     }
  1337. }
  1338.  
  1339. /* We don't wait for the result of a send because some telnets don't behave
  1340.  * correctly with WSAEINPROGRESS when sending. This results in characters
  1341.  * being dropped to hell while we wait for the response from the host.
  1342.  * We return success unless the socket is not connected or is closed.
  1343.  * This is fairly safe on connected sockets (which is what uses send).
  1344.  *
  1345.  * We don't do this with sendto because it's really only telnets that suffer
  1346.  * from this, although that doesn't stop another application from having the
  1347.  * same problem with sendto later on.
  1348.  *
  1349.  * This causes certain FTP clients to display phenomenal transfer rates.
  1350.  * They should be checking the transfer rates *after* closing their sockets.
  1351.  */
  1352. int pascal far _export send (SOCKET s, const char FAR * buf, int len, int flags)
  1353. {
  1354.     struct per_task *ppt;
  1355.     struct per_socket *pps;
  1356.     int    nReturn;
  1357.     struct    func_arg pfaArgs[4];
  1358.     struct    func_arg pfaReturn;
  1359.     struct    transmit_function tf;
  1360.  
  1361.     if ((ppt = GetTaskInfo()) == 0)
  1362.         return -1;
  1363.     if ((pps = GetSocketInfo(s)) == 0)
  1364.         return -1;
  1365.     if (!(pps->iFlags & PSF_CONNECT))
  1366.     {
  1367.         iErrno = WSAENOTCONN;
  1368.         return -1;
  1369.     }
  1370.     if (pps->iFlags & PSF_CLOSED)
  1371.     {
  1372.         iErrno = WSAECONNRESET;
  1373.         return -1;
  1374.     }
  1375.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1376.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    buf,        len            );
  1377.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &len,        sizeof(len)        );
  1378.     INIT_ARGS(pfaArgs[3],    AT_Int,        &flags,        sizeof(flags)        );
  1379.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1380.     INIT_TF(tf, FN_Send, 4, pfaArgs, pfaReturn);
  1381.     RemoveTXQ(TransmitFunction(&tf));
  1382.     Notify(pps, FD_WRITE);
  1383.     return len;
  1384. }
  1385.  
  1386. int pascal far _export sendto (SOCKET s, const char FAR * buf, int len, int flags,
  1387.                        const struct sockaddr FAR *to, int tolen)
  1388. {
  1389.     struct per_task *ppt;
  1390.     struct per_socket *pps;
  1391.     int    nReturn;
  1392.     struct    func_arg pfaArgs[6];
  1393.     struct    func_arg pfaReturn;
  1394.     struct    transmit_function tf;
  1395.     struct    sockaddr    *psa;
  1396.  
  1397.     if ((ppt = GetTaskInfo()) == 0)
  1398.         return -1;
  1399.     if ((pps = GetSocketInfo(s)) == 0)
  1400.         return -1;
  1401.     psa = (struct sockaddr *) malloc(tolen);
  1402.     memcpy(psa, to, tolen);
  1403.     psa->sa_family = htons(psa->sa_family);
  1404.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1405.     INIT_CARGS(pfaArgs[1],    AT_GenPtr,    buf,        len            );
  1406.     INIT_ARGS(pfaArgs[2],    AT_IntPtr,    &len,        sizeof(len)        );
  1407.     INIT_ARGS(pfaArgs[3],    AT_Int,        &flags,        sizeof(flags)        );
  1408.     INIT_CARGS(pfaArgs[4],    AT_GenPtr,    to,        tolen            );
  1409.     INIT_ARGS(pfaArgs[5],    AT_Int,        &tolen,        sizeof(tolen)        );
  1410.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1411.     INIT_TF(tf, FN_Send, 6, pfaArgs, pfaReturn);
  1412.     TransmitFunctionAndBlock(ppt, &tf);
  1413.     free(psa);
  1414.     Notify(pps, FD_WRITE);
  1415.     return nReturn;
  1416. }
  1417.  
  1418. int pascal far _export setsockopt (SOCKET s, int level, int optname,
  1419.                            const char FAR * optval, int optlen)
  1420. {
  1421.     struct per_task *ppt;
  1422.     struct per_socket *pps;
  1423.     int    nReturn;
  1424.     struct    func_arg pfaArgs[5];
  1425.     struct    func_arg pfaReturn;
  1426.     struct    transmit_function tf;
  1427.     long    iOptVal;
  1428.     short    iOptLen;
  1429.  
  1430.     iOptLen = sizeof(long);
  1431.  
  1432.     if ((ppt = GetTaskInfo()) == 0)
  1433.         return -1;
  1434.     if (!GetSocketInfo(s))
  1435.         return -1;
  1436.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1437.     INIT_ARGS(pfaArgs[1],    AT_Int,        &level,        sizeof(level)        );
  1438.     INIT_ARGS(pfaArgs[2],    AT_Int,        &optname,    sizeof(optname)        );
  1439.     if (optname == SO_LINGER)
  1440.     {
  1441.         INIT_ARGS(pfaArgs[3],    AT_GenPtr,    optval,        iOptLen        );
  1442.     }
  1443.     else
  1444.     {
  1445.         iOptVal = *optval;
  1446.         INIT_ARGS(pfaArgs[3],    AT_Int32Ptr,    &iOptVal,    iOptLen        );
  1447.     }
  1448.     INIT_ARGS(pfaArgs[4],    AT_Int,        &iOptLen,    sizeof(iOptLen)        );
  1449.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1450.     INIT_TF(tf, FN_SetSockOpt, 5, pfaArgs, pfaReturn);
  1451.     TransmitFunctionAndBlock(ppt, &tf);
  1452.     return nReturn;
  1453. }
  1454.  
  1455. int pascal far _export shutdown (SOCKET s, int how)
  1456. {
  1457.     struct per_task *ppt;
  1458.     struct per_socket *pps;
  1459.     int    nReturn;
  1460.     struct    func_arg pfaArgs[2];
  1461.     struct    func_arg pfaReturn;
  1462.     struct    transmit_function tf;
  1463.  
  1464.     if ((ppt = GetTaskInfo()) == 0)
  1465.         return -1;
  1466.     if ((pps = GetSocketInfo(s)) == 0)
  1467.         return -1;
  1468.     INIT_ARGS(pfaArgs[0],    AT_Int,        &s,        sizeof(s)        );
  1469.     INIT_ARGS(pfaArgs[1],    AT_Int,        &how,        sizeof(how)        );
  1470.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1471.     INIT_TF(tf, FN_Shutdown, 2, pfaArgs, pfaReturn);
  1472.     TransmitFunctionAndBlock(ppt, &tf);
  1473.     if (nReturn != -1 && (how == 0 || how == 2))
  1474.         pps->iFlags |= PSF_SHUTDOWN;
  1475.     return nReturn;
  1476. }
  1477.  
  1478. SOCKET pascal far _export socket (int af, int type, int protocol)
  1479. {
  1480.     struct per_task *ppt;
  1481.     struct per_socket *pps;
  1482.     int    nReturn;
  1483.     struct    func_arg pfaArgs[3];
  1484.     struct    func_arg pfaReturn;
  1485.     struct    transmit_function tf;
  1486.  
  1487.     if ((ppt = GetTaskInfo()) == 0)
  1488.         return -1;
  1489.     INIT_ARGS(pfaArgs[0],    AT_Int,        &af,        sizeof(af)        );
  1490.     INIT_ARGS(pfaArgs[1],    AT_Int,        &type,        sizeof(type)        );
  1491.     INIT_ARGS(pfaArgs[2],    AT_Int,        &protocol,    sizeof(protocol)    );
  1492.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1493.     INIT_TF(tf, FN_Socket, 3, pfaArgs, pfaReturn);
  1494.     TransmitFunctionAndBlock(ppt, &tf);
  1495.     if (nReturn != -1)
  1496.         NewSocket(ppt, nReturn);
  1497.     return nReturn;
  1498. }
  1499.  
  1500. struct hostent FAR * pascal far _export gethostbyaddr(const char FAR * addr,
  1501.                                               int len, int type)
  1502. {
  1503.     struct per_task *ppt;
  1504.     struct    func_arg pfaArgs[3];
  1505.     struct    func_arg pfaReturn;
  1506.     struct    transmit_function tf;
  1507.  
  1508.     if ((ppt = GetTaskInfo()) == 0)
  1509.         return 0;
  1510.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    addr,        len            );
  1511.     INIT_ARGS(pfaArgs[1],    AT_Int,        &len,        sizeof(len)        );
  1512.     INIT_ARGS(pfaArgs[2],    AT_Int,        &type,        sizeof(type)        );
  1513.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1514.     INIT_TF(tf, FN_HostByAddr, 3, pfaArgs, pfaReturn);
  1515.     if (TransmitFunctionAndBlock(ppt, &tf))
  1516.     {
  1517.         CopyHostEnt(ppt);
  1518.         return &ppt->he;
  1519.     }
  1520.     else
  1521.     {
  1522.         return 0;
  1523.     }
  1524. }
  1525.  
  1526. struct hostent FAR * pascal far _export gethostbyname(const char FAR * name)
  1527. {
  1528.     struct per_task *ppt;
  1529.     struct    func_arg pfaArgs[1];
  1530.     struct    func_arg pfaReturn;
  1531.     struct    transmit_function tf;
  1532.  
  1533.     if ((ppt = GetTaskInfo()) == 0)
  1534.         return 0;
  1535.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1536.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1537.     INIT_TF(tf, FN_HostByName, 1, pfaArgs, pfaReturn);
  1538.     if (TransmitFunctionAndBlock(ppt, &tf))
  1539.     {
  1540.         CopyHostEnt(ppt);
  1541.         return &ppt->he;
  1542.     }
  1543.     else
  1544.     {
  1545.         return 0;
  1546.     }
  1547. }
  1548.  
  1549. struct servent FAR * pascal far _export getservbyport(int port, const char FAR * proto)
  1550. {
  1551.     struct per_task *ppt;
  1552.     struct    func_arg pfaArgs[2];
  1553.     struct    func_arg pfaReturn;
  1554.     struct    transmit_function tf;
  1555.  
  1556.     if ((ppt = GetTaskInfo()) == 0)
  1557.         return 0;
  1558.     PORTSWAP(port);
  1559.     if (!proto)
  1560.         proto = "";
  1561.     INIT_ARGS(pfaArgs[0],    AT_Int,        &port,        sizeof(port)        );
  1562.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1563.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1564.     INIT_TF(tf, FN_ServByPort, 2, pfaArgs, pfaReturn);
  1565.     if (TransmitFunctionAndBlock(ppt, &tf))
  1566.     {
  1567.         CopyServEnt(ppt);
  1568.         return &ppt->se;
  1569.     }
  1570.     else
  1571.     {
  1572.         return 0;
  1573.     }
  1574. }
  1575.  
  1576. struct servent FAR * pascal far _export getservbyname(const char FAR * name,
  1577.                                               const char FAR * proto)
  1578. {
  1579.     struct per_task *ppt;
  1580.     struct    func_arg pfaArgs[2];
  1581.     struct    func_arg pfaReturn;
  1582.     struct    transmit_function tf;
  1583.  
  1584.     if ((ppt = GetTaskInfo()) == 0)
  1585.         return 0;
  1586.     if (!proto)
  1587.         proto = "";
  1588.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1589.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1590.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1591.     INIT_TF(tf, FN_ServByName, 2, pfaArgs, pfaReturn);
  1592.     if (TransmitFunctionAndBlock(ppt, &tf))
  1593.     {
  1594.         CopyServEnt(ppt);
  1595.         return &ppt->se;
  1596.     }
  1597.     else
  1598.     {
  1599.         return 0;
  1600.     }
  1601. }
  1602.  
  1603. struct protoent FAR * pascal far _export getprotobynumber(int proto)
  1604. {
  1605.     struct per_task *ppt;
  1606.     struct    func_arg pfaArgs[1];
  1607.     struct    func_arg pfaReturn;
  1608.     struct    transmit_function tf;
  1609.  
  1610.     if ((ppt = GetTaskInfo()) == 0)
  1611.         return 0;
  1612.     INIT_ARGS(pfaArgs[0],    AT_Int,        &proto,        sizeof(proto)    );
  1613.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT    );
  1614.     INIT_TF(tf, FN_ProtoByNumber, 1, pfaArgs, pfaReturn);
  1615.     if (TransmitFunctionAndBlock(ppt, &tf))
  1616.     {
  1617.         CopyProtoEnt(ppt);
  1618.         return &ppt->pe;
  1619.     }
  1620.     else
  1621.     {
  1622.         return 0;
  1623.     }
  1624. }
  1625.  
  1626. struct protoent FAR * pascal far _export getprotobyname(const char FAR * name)
  1627. {
  1628.     struct per_task *ppt;
  1629.     struct    func_arg pfaArgs[1];
  1630.     struct    func_arg pfaReturn;
  1631.     struct    transmit_function tf;
  1632.  
  1633.     if ((ppt = GetTaskInfo()) == 0)
  1634.         return 0;
  1635.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1636.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  1637.     INIT_TF(tf, FN_ProtoByName, 1, pfaArgs, pfaReturn);
  1638.     if (TransmitFunctionAndBlock(ppt, &tf))
  1639.     {
  1640.         CopyProtoEnt(ppt);
  1641.         return &ppt->pe;
  1642.     }
  1643.     else
  1644.     {
  1645.         return 0;
  1646.     }
  1647. }
  1648.  
  1649. int pascal far _export
  1650. gethostname(char *name, int namelen)
  1651. {
  1652.     struct per_task *ppt;
  1653.     int    nReturn;
  1654.     struct    func_arg pfaArgs[2];
  1655.     struct    func_arg pfaReturn;
  1656.     struct    transmit_function tf;
  1657.  
  1658.     if ((ppt = GetTaskInfo()) == 0)
  1659.         return -1;
  1660.     INIT_ARGS(pfaArgs[0],    AT_String,    name,        namelen        );
  1661.     INIT_ARGS(pfaArgs[1],    AT_Int,        &namelen,    sizeof(namelen)    );
  1662.     INIT_ARGS(pfaReturn,    AT_Int,        &nReturn,    sizeof(nReturn)        );
  1663.     INIT_TF(tf, FN_GetHostName, 2, pfaArgs, pfaReturn);
  1664.     TransmitFunctionAndBlock(ppt, &tf);
  1665.     return nReturn;
  1666. }
  1667.  
  1668. int pascal far _export WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData)
  1669. {
  1670.     struct    per_task    *pptNew;
  1671.  
  1672.     lpWSAData->wVersion = 0x0101;
  1673.     lpWSAData->wHighVersion = 0x0101;
  1674.     strcpy(lpWSAData->szDescription,
  1675.         "TwinSock 1.1 - Proxy sockets system. "
  1676.         "Copyright 1994 Troy Rollo. "
  1677.         "TwinSock is free software. "
  1678.         "See the file \"COPYING\" from the "
  1679.         "distribution for details.");
  1680.     if (!hwndManager)
  1681.         strcpy(lpWSAData->szSystemStatus, "Not Initialised.");
  1682.     else if (bEstablished)
  1683.         strcpy(lpWSAData->szSystemStatus, "Ready.");
  1684.     else
  1685.         strcpy(lpWSAData->szSystemStatus, "Initialising.");
  1686.     lpWSAData->iMaxSockets = 256;
  1687.     lpWSAData->iMaxUdpDg = 512;
  1688.     lpWSAData->lpVendorInfo = 0;
  1689.     if (wVersionRequired == 0x0001)
  1690.         return WSAVERNOTSUPPORTED;
  1691.     if (!bEstablished)
  1692.         return WSASYSNOTREADY;
  1693.     pptNew = malloc(sizeof(struct per_task));
  1694.     pptNew->htask = GetCurrentTask();
  1695.     pptNew->pptNext = pptList;
  1696.     pptNew->lpBlockFunc = 0;
  1697.     pptNew->bCancel = FALSE;
  1698.     pptNew->bBlocking = FALSE;
  1699.     pptList = pptNew;
  1700.     return 0;
  1701. }
  1702.  
  1703. int pascal far _export WSACleanup(void)
  1704. {
  1705.     struct    per_task *ppt;
  1706.  
  1707.     if ((ppt = GetTaskInfo()) == 0)
  1708.         return -1;
  1709.     if (ppt->bBlocking)
  1710.     {
  1711.         iErrno = WSAEINPROGRESS;
  1712.         RemoveTask(ppt);
  1713.         return -1;
  1714.     }
  1715.     return 0;
  1716. }
  1717.  
  1718. void pascal far _export WSASetLastError(int iError)
  1719. {
  1720.     if (!GetTaskInfo())
  1721.         return -1;
  1722.     iErrno = iError;
  1723. }
  1724.  
  1725. int pascal far _export WSAGetLastError(void)
  1726. {
  1727.     return iErrno;
  1728. }
  1729.  
  1730. BOOL pascal far _export WSAIsBlocking(void)
  1731. {
  1732.     struct per_task *ppt;
  1733.  
  1734.     if ((ppt = GetTaskInfo()) == 0)
  1735.         return -1;
  1736.     return ppt->bBlocking;
  1737. }
  1738.  
  1739. int pascal far _export WSAUnhookBlockingHook(void)
  1740. {
  1741.     struct    per_task *ppt;
  1742.  
  1743.     if ((ppt = GetTaskInfo()) == 0)
  1744.         return -1;
  1745.     ppt->lpBlockFunc = 0;
  1746.     return 0;
  1747. }
  1748.  
  1749. FARPROC pascal far _export WSASetBlockingHook(FARPROC lpBlockFunc)
  1750. {
  1751.     struct per_task *ppt;
  1752.  
  1753.     if ((ppt = GetTaskInfo()) == 0)
  1754.         return -1;
  1755.     ppt->lpBlockFunc = lpBlockFunc;
  1756.     return -1;
  1757. }
  1758.  
  1759. int pascal far _export WSACancelBlockingCall(void)
  1760. {
  1761.     struct    per_task *ppt;
  1762.  
  1763.     if ((ppt = GetTaskInfo()) == 0)
  1764.         return -1;
  1765.     if (ppt->bBlocking)
  1766.     {
  1767.         ppt->bCancel = TRUE;
  1768.         return 0;
  1769.     }
  1770.     else
  1771.     {
  1772.         iErrno = WSAEINVAL;
  1773.         return -1;
  1774.     }
  1775. }
  1776.  
  1777. static    void
  1778. FireAsyncRequest(struct tx_queue *ptxq)
  1779. {
  1780.     int    nLen;
  1781.     char    *pchData;
  1782.     struct    per_task *ppt;
  1783.  
  1784.     if (ptxq->ptxr->nError)
  1785.     {
  1786.         PostMessage(ptxq->hwnd, ptxq->wMsg, ptxq->id | 0x4000,
  1787.             WSAMAKEASYNCREPLY(0, ntohs(ptxq->ptxr->nError)));
  1788.         RemoveTXQ(ptxq);
  1789.         return;
  1790.     }
  1791.  
  1792.     ppt = GetAnotherTaskInfo(ptxq->htask);
  1793.  
  1794.     if (!ppt)
  1795.     {
  1796.         /* How **Rude** */
  1797.         RemoveTXQ(ptxq);
  1798.         return;
  1799.     }
  1800.  
  1801.     pchData = ptxq->ptxr->pchData +
  1802.         ntohs(ptxq->ptxr->nLen) -
  1803.         MAX_HOST_ENT -
  1804.         sizeof(short) * 5;
  1805.  
  1806.     switch(ptxq->ft)
  1807.     {
  1808.     case FN_HostByName:
  1809.     case FN_HostByAddr:
  1810.         memcpy(ppt->achHostEnt, pchData, MAX_HOST_ENT);
  1811.         nLen = CopyHostEntTo(ppt, ptxq->pchLocation);
  1812.         break;
  1813.  
  1814.     case FN_ServByName:
  1815.     case FN_ServByPort:
  1816.         memcpy(ppt->achServEnt, pchData, MAX_HOST_ENT);
  1817.         nLen = CopyServEntTo(ppt, ptxq->pchLocation);
  1818.         break;
  1819.  
  1820.     case FN_ProtoByName:
  1821.     case FN_ProtoByNumber:
  1822.         memcpy(ppt->achProtoEnt, pchData, MAX_HOST_ENT);
  1823.         nLen = CopyProtoEntTo(ppt, ptxq->pchLocation);
  1824.         break;
  1825.     }
  1826.  
  1827.     PostMessage(ptxq->hwnd, ptxq->wMsg, ptxq->id | 0x4000,
  1828.         WSAMAKEASYNCREPLY(nLen, 0));
  1829.     RemoveTXQ(ptxq);
  1830. }
  1831.  
  1832. HANDLE pascal far _export WSAAsyncGetServByName(HWND hWnd, u_int wMsg,
  1833.                                         const char FAR * name,
  1834.                     const char FAR * proto,
  1835.                                         char FAR * buf, int buflen)
  1836. {
  1837.     struct per_task *ppt;
  1838.     struct    func_arg pfaArgs[2];
  1839.     struct    func_arg pfaReturn;
  1840.     struct    transmit_function tf;
  1841.     struct    tx_queue *txq;
  1842.  
  1843.     if ((ppt = GetTaskInfo()) == 0)
  1844.         return 0;
  1845.     if (!proto)
  1846.         proto = "";
  1847.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1848.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1849.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1850.     INIT_TF(tf, FN_ServByName, 2, pfaArgs, pfaReturn);
  1851.     txq = TransmitFunction(&tf);
  1852.     txq->hwnd = hWnd;
  1853.     txq->pchLocation = buf;
  1854.     txq->wMsg = wMsg;
  1855.     txq->ft = FN_ServByName;
  1856.     txq->htask = ppt->htask;
  1857.     return (txq->id | 0x4000);
  1858. }
  1859.  
  1860. HANDLE pascal far _export WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, int port,
  1861.                                         const char FAR * proto, char FAR * buf,
  1862.                                         int buflen)
  1863. {
  1864.     struct per_task *ppt;
  1865.     struct    func_arg pfaArgs[2];
  1866.     struct    func_arg pfaReturn;
  1867.     struct    transmit_function tf;
  1868.     struct    tx_queue *txq;
  1869.  
  1870.     if ((ppt = GetTaskInfo()) == 0)
  1871.         return 0;
  1872.     port = PORTSWAP(port);
  1873.     if (!proto)
  1874.         proto = "";
  1875.     INIT_CARGS(pfaArgs[0],    AT_Int,        &port,        sizeof(port)        );
  1876.     INIT_CARGS(pfaArgs[1],    AT_String,    proto,        strlen(proto) + 1    );
  1877.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achServEnt,MAX_HOST_ENT        );
  1878.     INIT_TF(tf, FN_ServByPort, 2, pfaArgs, pfaReturn);
  1879.     txq = TransmitFunction(&tf);
  1880.     txq->hwnd = hWnd;
  1881.     txq->pchLocation = buf;
  1882.     txq->wMsg = wMsg;
  1883.     txq->ft = FN_ServByPort;
  1884.     txq->htask = ppt->htask;
  1885.     return (txq->id | 0x4000);
  1886. }
  1887.  
  1888. HANDLE pascal far _export WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,
  1889.                                          const char FAR * name, char FAR * buf,
  1890.                                          int buflen)
  1891. {
  1892.     struct per_task *ppt;
  1893.     struct    func_arg pfaArgs[1];
  1894.     struct    func_arg pfaReturn;
  1895.     struct    transmit_function tf;
  1896.     struct    tx_queue *txq;
  1897.  
  1898.     if ((ppt = GetTaskInfo()) == 0)
  1899.         return 0;
  1900.     INIT_CARGS(pfaArgs[0],    AT_String,    name,        strlen(name) + 1    );
  1901.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  1902.     INIT_TF(tf, FN_ProtoByName, 1, pfaArgs, pfaReturn);
  1903.     txq = TransmitFunction(&tf);
  1904.     txq->hwnd = hWnd;
  1905.     txq->pchLocation = buf;
  1906.     txq->wMsg = wMsg;
  1907.     txq->ft = FN_ProtoByName;
  1908.     txq->htask = ppt->htask;
  1909.     return (txq->id | 0x4000);
  1910. }
  1911.  
  1912. HANDLE pascal far _export WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,
  1913.                                            int number, char FAR * buf,
  1914.                                            int buflen)
  1915. {
  1916.     struct per_task *ppt;
  1917.     struct    func_arg pfaArgs[1];
  1918.     struct    func_arg pfaReturn;
  1919.     struct    transmit_function tf;
  1920.     struct    tx_queue *txq;
  1921.  
  1922.     if ((ppt = GetTaskInfo()) == 0)
  1923.         return 0;
  1924.     INIT_CARGS(pfaArgs[0],    AT_Int,        &number,    sizeof(number)        );
  1925.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achProtoEnt,MAX_HOST_ENT        );
  1926.     INIT_TF(tf, FN_ProtoByNumber, 1, pfaArgs, pfaReturn);
  1927.     txq = TransmitFunction(&tf);
  1928.     txq->hwnd = hWnd;
  1929.     txq->pchLocation = buf;
  1930.     txq->wMsg = wMsg;
  1931.     txq->ft = FN_ProtoByNumber;
  1932.     txq->htask = ppt->htask;
  1933.     return (txq->id | 0x4000);
  1934. }
  1935.  
  1936. HANDLE pascal far _export WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
  1937.                                         const char FAR * name, char FAR * buf,
  1938.                                         int buflen)
  1939. {
  1940.     struct per_task *ppt;
  1941.     struct    func_arg pfaArgs[1];
  1942.     struct    func_arg pfaReturn;
  1943.     struct    transmit_function tf;
  1944.     struct    tx_queue *txq;
  1945.  
  1946.     if ((ppt = GetTaskInfo()) == 0)
  1947.         return 0;
  1948.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    name,        strlen(name) + 1    );
  1949.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1950.     INIT_TF(tf, FN_HostByName, 1, pfaArgs, pfaReturn);
  1951.     txq = TransmitFunction(&tf);
  1952.     txq->hwnd = hWnd;
  1953.     txq->pchLocation = buf;
  1954.     txq->wMsg = wMsg;
  1955.     txq->ft = FN_HostByName;
  1956.     txq->htask = ppt->htask;
  1957.     return (txq->id | 0x4000);
  1958. }
  1959.  
  1960. HANDLE pascal far _export WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg,
  1961.                                         const char FAR * addr, int len, int type,
  1962.                                         char FAR * buf, int buflen)
  1963. {
  1964.     struct per_task *ppt;
  1965.     struct    func_arg pfaArgs[3];
  1966.     struct    func_arg pfaReturn;
  1967.     struct    transmit_function tf;
  1968.     struct    tx_queue *txq;
  1969.  
  1970.     if ((ppt = GetTaskInfo()) == 0)
  1971.         return 0;
  1972.     INIT_CARGS(pfaArgs[0],    AT_GenPtr,    addr,        len            );
  1973.     INIT_CARGS(pfaArgs[1],    AT_Int,        &len,        sizeof(len)        );
  1974.     INIT_CARGS(pfaArgs[2],    AT_Int,        &type,        sizeof(type)        );
  1975.     INIT_ARGS(pfaReturn,    AT_GenPtr,    ppt->achHostEnt,MAX_HOST_ENT        );
  1976.     INIT_TF(tf, FN_HostByAddr, 3, pfaArgs, pfaReturn);
  1977.     txq = TransmitFunction(&tf);
  1978.     txq->hwnd = hWnd;
  1979.     txq->pchLocation = buf;
  1980.     txq->wMsg = wMsg;
  1981.     txq->ft = FN_HostByAddr;
  1982.     txq->htask = ppt->htask;
  1983.     return (txq->id | 0x4000);
  1984. }
  1985.  
  1986. int pascal far _export WSACancelAsyncRequest(HANDLE hAsyncTaskHandle)
  1987. {
  1988.     struct    tx_queue *ptxq;
  1989.  
  1990.     if (!GetTaskInfo())
  1991.         return -1;
  1992.  
  1993.     for (ptxq = ptxqList; ptxq; ptxq = ptxq->ptxqNext)
  1994.     {
  1995.         if ((HANDLE) (ptxq->id | 0x4000) == hAsyncTaskHandle)
  1996.         {
  1997.             RemoveTXQ(ptxq);
  1998.             return 0;
  1999.         }
  2000.     }
  2001.     iErrno = WSAEINVAL;
  2002.     return -1;
  2003. }
  2004.  
  2005. int pascal far _export WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg,
  2006.                                long lEvent)
  2007. {
  2008.     struct    per_task *ppt;
  2009.     struct    per_socket *pps;
  2010.  
  2011.     if ((ppt = GetTaskInfo()) == 0)
  2012.         return -1;
  2013.     if ((pps = GetSocketInfo(s)) == 0)
  2014.         return -1;
  2015.     if (lEvent)
  2016.         pps->iFlags |= PSF_NONBLOCK;
  2017.     pps->hWnd = hWnd;
  2018.     pps->wMsg = wMsg;
  2019.     pps->iEvents = lEvent;
  2020.     Notify(pps, FD_WRITE);
  2021.     if (pps->pdIn)
  2022.         Notify(pps, (pps->iFlags & PSF_ACCEPT) ?
  2023.                 FD_ACCEPT :
  2024.                 (pps->pdIn->iLen ?
  2025.                     FD_READ :
  2026.                     FD_CLOSE));
  2027.     return 0;
  2028. }
  2029.  
  2030. int FAR PASCAL _export _WSAFDIsSet(SOCKET s, fd_set FAR *pfds)
  2031. {
  2032.     int    i;
  2033.  
  2034.     if (!GetTaskInfo())
  2035.         return -1;
  2036.     if (!GetSocketInfo(s))
  2037.         return -1;
  2038.     for (i = 0; i < pfds->fd_count; i++)
  2039.     {
  2040.         if (pfds->fd_array[i] == s)
  2041.             return TRUE;
  2042.     }
  2043.     return FALSE;
  2044. }
  2045.  
  2046.  
  2047.